package net.alexguev.eclipse.refactoring.rename;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.refactoring.IJavaRefactorings;
import org.eclipse.jdt.core.refactoring.descriptors.MoveDescriptor;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
import org.eclipse.ltk.core.refactoring.participants.MoveParticipant;

public class TestFixtureMoveParticipant extends MoveParticipant {

	private Object element;
	private IType targetType;
	
	public TestFixtureMoveParticipant() {
	} 

	@Override
	public RefactoringStatus checkConditions(IProgressMonitor pm, CheckConditionsContext context) throws OperationCanceledException {
		return new RefactoringStatus();
	}

	@Override
	public Change createChange(IProgressMonitor pm) throws CoreException, OperationCanceledException {
		if (Activator.getDefault().creatingChange) {
			return null;
		}
		
		try {
			Activator.getDefault().creatingChange = true;
			return doCreateChange(pm);
		
		} finally {
			Activator.getDefault().creatingChange = false;
		}
	}

	private Change doCreateChange(IProgressMonitor pm) throws CoreException {
		if (this.element instanceof IType) {
			this.targetType = (IType) this.element;
			
			if (!isPrimaryCompilationUnit()) {
				return null;
			}

			IJavaProject javaProject = this.targetType.getJavaProject();
			try {
				IType participantType = javaProject.findType(this.targetType.getFullyQualifiedName() + "Test" );
				
				if (participantType==null) {
					if (this.targetType.getFullyQualifiedName().endsWith("Test")) {
						participantType = javaProject.findType(this.targetType.getFullyQualifiedName().replaceFirst("Test\\z", ""));
					}
				}
				
				if (participantType!=null) {
					MoveDescriptor descriptor = (MoveDescriptor) RefactoringCore.getRefactoringContribution(
							IJavaRefactorings.MOVE).createDescriptor();
					descriptor.setMoveResources(new IFile[] {}, new IFolder[] {}, new ICompilationUnit[] {participantType.getCompilationUnit()});
					descriptor.setUpdateReferences(true);
					descriptor.setDestination((IJavaElement) getArguments().getDestination());
					Refactoring refactoring = descriptor.createRefactoring(new RefactoringStatus());
					if (!refactoring.checkInitialConditions(pm).isOK()) {
						return null;
					}
					if (!refactoring.checkFinalConditions(pm).isOK()) {
						return null;
					}
					return refactoring.createChange(pm);
				}
			} catch (JavaModelException e) {
				//TODO: log! 
				e.printStackTrace();
			}
			
		}
		return null;
	}

	private boolean isPrimaryCompilationUnit() {
		return this.targetType.getParent().equals(this.targetType.getCompilationUnit());
	}

	@Override
	public String getName() {
		return "TestFixtureRenameParticipant";
	}

	@Override
	protected boolean initialize(Object element) {
		this.element = element;
		return true;
	}

}
